package com.alibaba.dingtalk.openapi.auth;

import com.alibaba.dingtalk.openapi.Env;
import com.alibaba.dingtalk.openapi.OApiException;
import com.alibaba.dingtalk.openapi.user.UserHelper;
import com.alibaba.dingtalk.openapi.utils.FileUtils;
import com.alibaba.dingtalk.openapi.utils.HttpHelper;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.oapi.lib.aes.DingTalkJsApiSingnature;
import com.dingtalk.open.client.ServiceFactory;
import com.dingtalk.open.client.api.model.corp.CorpUserBaseInfo;
import com.dingtalk.open.client.api.model.corp.CorpUserDetail;
import com.dingtalk.open.client.api.model.corp.JsapiTicket;
import com.dingtalk.open.client.api.service.corp.CorpConnectionService;
import com.dingtalk.open.client.api.service.corp.JsapiService;
import com.system.UserSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/auth")
/**
 * AccessToken和jsticket的获取封装
 */
public class AuthHelper {

    // 调整到1小时50分钟
    public static final long cacheTime = 1000 * 60 * 55 * 2;

    /*
     * 在此方法中，为了避免频繁获取access_token，
     * 在距离上一次获取access_token时间在两个小时之内的情况，
     * 将直接从持久化存储中读取access_token
     *
     * 因为access_token和jsapi_ticket的过期时间都是7200秒
     * 所以在获取access_token的同时也去获取了jsapi_ticket
     * 注：jsapi_ticket是在前端页面JSAPI做权限验证配置的时候需要使用的
     * 具体信息请查看开发者文档--权限验证配置
     */
    public static String getAccessToken() throws OApiException {
        long curTime = System.currentTimeMillis();
        JSONObject accessTokenValue = (JSONObject) FileUtils.getValue("accesstoken", Env.CORP_ID);
        String accToken = "";
        JSONObject jsontemp = new JSONObject();
        if (accessTokenValue == null || curTime - accessTokenValue.getLong("begin_time") >= cacheTime) {
            try {
                ServiceFactory serviceFactory = ServiceFactory.getInstance();
                CorpConnectionService corpConnectionService = serviceFactory.getOpenService(CorpConnectionService.class);
                accToken = corpConnectionService.getCorpToken(Env.CORP_ID, Env.CORP_SECRET);
                // save accessToken
                JSONObject jsonAccess = new JSONObject();
                jsontemp.clear();
                jsontemp.put("access_token", accToken);
                jsontemp.put("begin_time", curTime);
                jsonAccess.put(Env.CORP_ID, jsontemp);
                //真实项目中最好保存到数据库中
                FileUtils.write2File(jsonAccess, "accesstoken");

            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            return accessTokenValue.getString("access_token");
        }

        return accToken;
    }

    /**
     * 获取JSTicket, 用于js的签名计算
     * 正常的情况下，jsapi_ticket的有效期为7200秒，所以开发者需要在某个地方设计一个定时器，定期去更新jsapi_ticket
     */
    public static String getJsapiTicket(String accessToken) throws OApiException {
        JSONObject jsTicketValue = (JSONObject) FileUtils.getValue("jsticket", Env.CORP_ID);
        long curTime = System.currentTimeMillis();
        String jsTicket = "";

        if (jsTicketValue == null || curTime -
                jsTicketValue.getLong("begin_time") >= cacheTime) {
            ServiceFactory serviceFactory;
            try {
                /********************************************************8*/
                /*JSONObject obj = HttpHelper.httpGet(Env.OAPI_HOST + "/get_jsapi_ticket?access_token=" + accessToken);
                if(new Integer(obj.getString("errcode")) == 0){
                    System.out.println("重新获取ticket=============");
                    jsTicket = obj.getString("ticket");
                }*/

                /********************************************************8*/
                serviceFactory = ServiceFactory.getInstance();
                JsapiService jsapiService = serviceFactory.getOpenService(JsapiService.class);

                JsapiTicket JsapiTicket = jsapiService.getJsapiTicket(accessToken, "jsapi");
                jsTicket = JsapiTicket.getTicket();

                JSONObject jsonTicket = new JSONObject();
                JSONObject jsontemp = new JSONObject();
                jsontemp.clear();
                jsontemp.put("ticket", jsTicket);
                jsontemp.put("begin_time", curTime);
                jsonTicket.put(Env.CORP_ID, jsontemp);
                FileUtils.write2File(jsonTicket, "jsticket");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return jsTicket;
        } else {
            return jsTicketValue.getString("ticket");
        }
    }


    public static String sign(String ticket, String nonceStr, long timeStamp, String url) throws OApiException {
        try {
            return DingTalkJsApiSingnature.getJsApiSingnature(url, nonceStr, timeStamp, ticket);
        } catch (Exception ex) {
            throw new OApiException(0, ex.getMessage());
        }
    }

    @RequestMapping(value = "/getPcJsConfig",method = RequestMethod.GET)
    @ResponseBody
    public Map<String,Object> getPcJsConfig(HttpServletRequest request){
        String urlString = request.getRequestURL().toString();
        String queryString = request.getQueryString();
        String queryStringEncode = null;
        String url;
        if (queryString != null) {
            queryStringEncode = URLDecoder.decode(queryString);
            url = urlString + "?" + queryStringEncode;
        } else {
            url = Env.PC_DOMAIN;
        }
        return getConfig(url);
    }

    @RequestMapping(value = "/getJsConfig",method = RequestMethod.GET)
    @ResponseBody
    public Map<String,Object> getJsConfig(HttpServletRequest request){
        String urlString = request.getRequestURL().toString();
        String queryString = request.getQueryString();
        String queryStringEncode = null;
        String url;
        if (queryString != null) {
            queryStringEncode = URLDecoder.decode(queryString);
            url = urlString + "?" + queryStringEncode;
        } else {
            url = Env.MOB_DOMAIN;
        }
        return getConfig(url);
    }

    /**
     * 计算当前请求的jsapi的签名数据<br/>
     * <p>
     * 如果签名数据是通过ajax异步请求的话，签名计算中的url必须是给用户展示页面的url
     *
     * //@param request
     * @return
     */
    public static Map<String,Object> getConfig(String queryUrl) {

        String nonceStr = "abcdefg";
        long timeStamp = System.currentTimeMillis() / 1000;
        String signedUrl = queryUrl;
        String accessToken = null;
        String ticket = null;
        String signature = null;
        Integer agentid = null;

        try {
            accessToken = AuthHelper.getAccessToken();

            ticket = AuthHelper.getJsapiTicket(accessToken);
            signature = AuthHelper.sign(ticket, nonceStr, timeStamp, signedUrl);
            agentid = Env.AGENT_ID;

        } catch (OApiException e) {
            e.printStackTrace();
        }
        String configValue = "{jsticket:'" + ticket + "',signature:'" + signature + "',nonceStr:'" + nonceStr + "',timeStamp:'"
                + timeStamp + "',corpId:'" + Env.CORP_ID + "',agentId:'" + agentid + "'}";
        System.out.println(configValue);
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("signature",signature);
        map.put("nonceStr",nonceStr);
        map.put("timeStamp",timeStamp);
        map.put("corpId",Env.CORP_ID);
        map.put("agentId",agentid);
        map.put("type",0);
        return map;
    }

    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public static Map<String,Object> login(HttpServletRequest request) throws Exception{
        String code = request.getParameter("code");
        String access_token = getAccessToken();
        Map<String,Object> map = new HashMap<String,Object>();
        try {
            CorpUserBaseInfo CorpUserBaseInfo = UserHelper.getUserInfo(access_token,code);
            if(CorpUserBaseInfo != null && CorpUserBaseInfo.getUserid() != null){
                CorpUserDetail user = UserHelper.getUser(access_token,CorpUserBaseInfo.getUserid());
                Map<String,Object> mapUser = new HashMap<String,Object>();
                mapUser.put("userId",user.getUserid());
                mapUser.put("department",user.getDepartment());
                mapUser.put("mobile",user.getMobile());
                mapUser.put("email",user.getEmail());
                mapUser.put("isHide",user.getIsHide());
                mapUser.put("jobnumber",user.getJobnumber());
                mapUser.put("avatar",user.getAvatar());
                mapUser.put("isAdmin",user.getIsAdmin());
                mapUser.put("name",user.getName());
                map.put("user",mapUser);
                UserSession userSession = new UserSession();
                //	userSession.token = token;
                //	userSession.ip = ip;
                userSession.userId = user.getUserid();
                userSession.userName = user.getName();
                userSession.jobNumber = user.getJobnumber();
                userSession.avatar = user.getAvatar();
                userSession.isAdmin = user.getIsAdmin();
                request.getSession().setAttribute("userSession", userSession);
            }
        }catch (Exception e){
            throw new Exception("错了");
        }
        return map;
    }

    public static String getSsoToken() throws OApiException {
        String url = "https://oapi.dingtalk.com/sso/gettoken?corpid=" + Env.CORP_ID + "&corpsecret=" + Env.SSO_Secret;
        JSONObject response = HttpHelper.httpGet(url);
        String ssoToken;
        if (response.containsKey("access_token")) {
            ssoToken = response.getString("access_token");
        } else {
            throw new OApiException("Sso_token");
        }
        return ssoToken;

    }

}
